using System;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using Newtonsoft.Json;

namespace GenerativeAgents.Core
{
    /// <summary>
    /// 数据持久化系统
    /// 负责智能体记忆和状态的保存与加载
    /// </summary>
    public class DataPersistence : MonoBehaviour
    {
        [Header("持久化配置")]
        [SerializeField] private string saveDataPath = "GenerativeAgents";
        [SerializeField] private bool autoSaveEnabled = true;
        [SerializeField] private float autoSaveInterval = 300f; // 5分钟
        [SerializeField] private int maxBackupFiles = 5;
        [SerializeField] private bool enableDataLogging = false;
        
        [Header("数据压缩")]
        [SerializeField] private bool compressData = true;
        [SerializeField] private bool encryptData = false;
        
        // 文件路径
        private string dataDirectory;
        private string memoryFilePath;
        private string scratchFilePath;
        private string spatialFilePath;
        private string configFilePath;
        
        // 自动保存
        private float lastSaveTime;
        private bool isDirty = false;
        
        // 统计信息
        private int totalSaves = 0;
        private int totalLoads = 0;
        private DateTime lastSaveTimestamp;
        private DateTime lastLoadTimestamp;
        
        // 事件
        public event System.Action OnSaveStarted;
        public event System.Action OnSaveCompleted;
        public event System.Action OnLoadStarted;
        public event System.Action OnLoadCompleted;
        public event System.Action<string> OnSaveError;
        public event System.Action<string> OnLoadError;
        
        private void Awake()
        {
            InitializeDataPersistence();
        }
        
        private void Start()
        {
            LoadConfigurationData();
        }
        
        private void Update()
        {
            if (autoSaveEnabled && isDirty)
            {
                CheckAutoSave();
            }
        }
        
        private void OnApplicationPause(bool pauseStatus)
        {
            if (pauseStatus)
            {
                SaveAllData();
            }
        }
        
        private void OnApplicationFocus(bool hasFocus)
        {
            if (!hasFocus)
            {
                SaveAllData();
            }
        }
        
        private void OnDestroy()
        {
            SaveAllData();
        }
        
        /// <summary>
        /// 初始化数据持久化系统
        /// </summary>
        private void InitializeDataPersistence()
        {
            // 设置数据目录
            dataDirectory = Path.Combine(Application.persistentDataPath, saveDataPath);
            
            // 确保目录存在
            if (!Directory.Exists(dataDirectory))
            {
                Directory.CreateDirectory(dataDirectory);
            }
            
            // 设置文件路径
            memoryFilePath = Path.Combine(dataDirectory, "memories.json");
            scratchFilePath = Path.Combine(dataDirectory, "scratch.json");
            spatialFilePath = Path.Combine(dataDirectory, "spatial.json");
            configFilePath = Path.Combine(dataDirectory, "config.json");
            
            lastSaveTime = Time.time;
            
            if (enableDataLogging)
            {
                Debug.Log($"[DataPersistence] Initialized with data directory: {dataDirectory}");
            }
        }
        
        /// <summary>
        /// 检查自动保存
        /// </summary>
        private void CheckAutoSave()
        {
            if (Time.time - lastSaveTime >= autoSaveInterval)
            {
                SaveAllData();
                lastSaveTime = Time.time;
            }
        }
        
        /// <summary>
        /// 保存所有数据
        /// </summary>
        public void SaveAllData()
        {
            try
            {
                OnSaveStarted?.Invoke();
                
                var memorySystem = FindObjectOfType<MemorySystem>();
                if (memorySystem != null)
                {
                    SaveMemories(memorySystem);
                }
                
                var agentController = FindObjectOfType<AgentController>();
                if (agentController != null)
                {
                    SaveScratchMemory(agentController);
                }
                
                SaveConfiguration();
                
                isDirty = false;
                totalSaves++;
                lastSaveTimestamp = DateTime.Now;
                
                OnSaveCompleted?.Invoke();
                
                if (enableDataLogging)
                {
                    Debug.Log("[DataPersistence] All data saved successfully");
                }
            }
            catch (Exception ex)
            {
                var errorMsg = $"Failed to save all data: {ex.Message}";
                Debug.LogError($"[DataPersistence] {errorMsg}");
                OnSaveError?.Invoke(errorMsg);
            }
        }
        
        /// <summary>
        /// 加载所有数据
        /// </summary>
        public void LoadAllData()
        {
            try
            {
                OnLoadStarted?.Invoke();
                
                LoadConfiguration();
                
                var memorySystem = FindObjectOfType<MemorySystem>();
                if (memorySystem != null)
                {
                    LoadMemories(memorySystem);
                }
                
                var agentController = FindObjectOfType<AgentController>();
                if (agentController != null)
                {
                    LoadScratchMemory(agentController);
                }
                
                totalLoads++;
                lastLoadTimestamp = DateTime.Now;
                
                OnLoadCompleted?.Invoke();
                
                if (enableDataLogging)
                {
                    Debug.Log("[DataPersistence] All data loaded successfully");
                }
            }
            catch (Exception ex)
            {
                var errorMsg = $"Failed to load all data: {ex.Message}";
                Debug.LogError($"[DataPersistence] {errorMsg}");
                OnLoadError?.Invoke(errorMsg);
            }
        }
        
        /// <summary>
        /// 保存记忆数据
        /// </summary>
        public void SaveMemories(MemorySystem memorySystem)
        {
            try
            {
                var memoryData = new MemoryPersistenceData
                {
                    version = "1.0",
                    timestamp = DateTime.Now,
                    associativeMemories = SerializeAssociativeMemories(memorySystem.AssociativeMemory),
                    spatialMemory = SerializeSpatialMemory(memorySystem.SpatialMemory)
                };
                
                var json = JsonConvert.SerializeObject(memoryData, Formatting.Indented);
                
                if (compressData)
                {
                    json = CompressString(json);
                }
                
                // 创建备份
                CreateBackup(memoryFilePath);
                
                File.WriteAllText(memoryFilePath, json);
                
                if (enableDataLogging)
                {
                    Debug.Log($"[DataPersistence] Memories saved: {memoryData.associativeMemories.Count} memories");
                }
            }
            catch (Exception ex)
            {
                Debug.LogError($"[DataPersistence] Error saving memories: {ex.Message}");
                throw;
            }
        }
        
        /// <summary>
        /// 加载记忆数据
        /// </summary>
        public void LoadMemories(MemorySystem memorySystem)
        {
            try
            {
                if (!File.Exists(memoryFilePath))
                {
                    if (enableDataLogging)
                    {
                        Debug.Log("[DataPersistence] No memory file found, starting with empty memories");
                    }
                    return;
                }
                
                var json = File.ReadAllText(memoryFilePath);
                
                if (compressData)
                {
                    json = DecompressString(json);
                }
                
                var memoryData = JsonConvert.DeserializeObject<MemoryPersistenceData>(json);
                
                if (memoryData != null)
                {
                    DeserializeAssociativeMemories(memoryData.associativeMemories, memorySystem.AssociativeMemory);
                    DeserializeSpatialMemory(memoryData.spatialMemory, memorySystem.SpatialMemory);
                    
                    if (enableDataLogging)
                    {
                        Debug.Log($"[DataPersistence] Memories loaded: {memoryData.associativeMemories.Count} memories");
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.LogError($"[DataPersistence] Error loading memories: {ex.Message}");
                throw;
            }
        }
        
        /// <summary>
        /// 保存短期记忆
        /// </summary>
        public void SaveScratchMemory(AgentController agentController)
        {
            try
            {
                var scratchData = new ScratchPersistenceData
                {
                    version = "1.0",
                    timestamp = DateTime.Now,
                    scratchMemory = SerializeScratchMemory(agentController.ScratchMemory)
                };
                
                var json = JsonConvert.SerializeObject(scratchData, Formatting.Indented);
                File.WriteAllText(scratchFilePath, json);
                
                if (enableDataLogging)
                {
                    Debug.Log("[DataPersistence] Scratch memory saved");
                }
            }
            catch (Exception ex)
            {
                Debug.LogError($"[DataPersistence] Error saving scratch memory: {ex.Message}");
                throw;
            }
        }
        
        /// <summary>
        /// 加载短期记忆
        /// </summary>
        public void LoadScratchMemory(AgentController agentController)
        {
            try
            {
                if (!File.Exists(scratchFilePath))
                {
                    if (enableDataLogging)
                    {
                        Debug.Log("[DataPersistence] No scratch memory file found, using defaults");
                    }
                    return;
                }
                
                var json = File.ReadAllText(scratchFilePath);
                var scratchData = JsonConvert.DeserializeObject<ScratchPersistenceData>(json);
                
                if (scratchData != null)
                {
                    DeserializeScratchMemory(scratchData.scratchMemory, agentController.ScratchMemory);
                    
                    if (enableDataLogging)
                    {
                        Debug.Log("[DataPersistence] Scratch memory loaded");
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.LogError($"[DataPersistence] Error loading scratch memory: {ex.Message}");
                throw;
            }
        }
        
        /// <summary>
        /// 保存配置数据
        /// </summary>
        private void SaveConfiguration()
        {
            try
            {
                var configData = new ConfigPersistenceData
                {
                    version = "1.0",
                    timestamp = DateTime.Now,
                    autoSaveEnabled = autoSaveEnabled,
                    autoSaveInterval = autoSaveInterval,
                    compressData = compressData,
                    encryptData = encryptData,
                    maxBackupFiles = maxBackupFiles,
                    totalSaves = totalSaves,
                    totalLoads = totalLoads,
                    lastSaveTimestamp = lastSaveTimestamp,
                    lastLoadTimestamp = lastLoadTimestamp
                };
                
                var json = JsonConvert.SerializeObject(configData, Formatting.Indented);
                File.WriteAllText(configFilePath, json);
            }
            catch (Exception ex)
            {
                Debug.LogError($"[DataPersistence] Error saving configuration: {ex.Message}");
            }
        }
        
        /// <summary>
        /// 加载配置数据
        /// </summary>
        private void LoadConfigurationData()
        {
            try
            {
                if (!File.Exists(configFilePath))
                    return;
                
                var json = File.ReadAllText(configFilePath);
                var configData = JsonConvert.DeserializeObject<ConfigPersistenceData>(json);
                
                if (configData != null)
                {
                    totalSaves = configData.totalSaves;
                    totalLoads = configData.totalLoads;
                    lastSaveTimestamp = configData.lastSaveTimestamp;
                    lastLoadTimestamp = configData.lastLoadTimestamp;
                }
            }
            catch (Exception ex)
            {
                Debug.LogError($"[DataPersistence] Error loading configuration: {ex.Message}");
            }
        }
        
        /// <summary>
        /// 序列化联想记忆
        /// </summary>
        private List<SerializableMemoryNode> SerializeAssociativeMemories(AssociativeMemory associativeMemory)
        {
            var serializedMemories = new List<SerializableMemoryNode>();
            
            foreach (var memory in associativeMemory.GetAllMemories())
            {
                if (!memory.CheckExpired()) // 只保存未过期的记忆
                {
                    serializedMemories.Add(new SerializableMemoryNode(memory));
                }
            }
            
            return serializedMemories;
        }
        
        /// <summary>
        /// 反序列化联想记忆
        /// </summary>
        private void DeserializeAssociativeMemories(List<SerializableMemoryNode> serializedMemories, AssociativeMemory associativeMemory)
        {
            associativeMemory.ClearAllMemories();
            
            foreach (var serializedMemory in serializedMemories)
            {
                var memory = serializedMemory.ToMemoryNode();
                if (memory != null && !memory.CheckExpired())
                {
                    associativeMemory.AddMemory(memory);
                }
            }
        }
        
        /// <summary>
        /// 序列化空间记忆
        /// </summary>
        private SerializableSpatialMemory SerializeSpatialMemory(SpatialMemory spatialMemory)
        {
            return new SerializableSpatialMemory(spatialMemory);
        }
        
        /// <summary>
        /// 反序列化空间记忆
        /// </summary>
        private void DeserializeSpatialMemory(SerializableSpatialMemory serializedSpatial, SpatialMemory spatialMemory)
        {
            serializedSpatial?.RestoreTo(spatialMemory);
        }
        
        /// <summary>
        /// 序列化短期记忆
        /// </summary>
        private SerializableScratchMemory SerializeScratchMemory(ScratchMemory scratchMemory)
        {
            return new SerializableScratchMemory(scratchMemory);
        }
        
        /// <summary>
        /// 反序列化短期记忆
        /// </summary>
        private void DeserializeScratchMemory(SerializableScratchMemory serializedScratch, ScratchMemory scratchMemory)
        {
            serializedScratch?.RestoreTo(scratchMemory);
        }
        
        /// <summary>
        /// 创建备份文件
        /// </summary>
        private void CreateBackup(string originalFilePath)
        {
            try
            {
                if (!File.Exists(originalFilePath))
                    return;
                
                var backupDir = Path.Combine(dataDirectory, "backups");
                if (!Directory.Exists(backupDir))
                {
                    Directory.CreateDirectory(backupDir);
                }
                
                var fileName = Path.GetFileNameWithoutExtension(originalFilePath);
                var extension = Path.GetExtension(originalFilePath);
                var timestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss");
                var backupPath = Path.Combine(backupDir, $"{fileName}_{timestamp}{extension}");
                
                File.Copy(originalFilePath, backupPath);
                
                // 清理旧备份
                CleanupOldBackups(backupDir, fileName);
            }
            catch (Exception ex)
            {
                Debug.LogWarning($"[DataPersistence] Failed to create backup: {ex.Message}");
            }
        }
        
        /// <summary>
        /// 清理旧备份
        /// </summary>
        private void CleanupOldBackups(string backupDir, string filePrefix)
        {
            try
            {
                var backupFiles = Directory.GetFiles(backupDir, $"{filePrefix}_*")
                    .OrderByDescending(f => File.GetCreationTime(f))
                    .Skip(maxBackupFiles)
                    .ToList();
                
                foreach (var file in backupFiles)
                {
                    File.Delete(file);
                }
            }
            catch (Exception ex)
            {
                Debug.LogWarning($"[DataPersistence] Failed to cleanup old backups: {ex.Message}");
            }
        }
        
        /// <summary>
        /// 压缩字符串
        /// </summary>
        private string CompressString(string text)
        {
            // 简化的压缩实现 - 在实际项目中应该使用真正的压缩算法
            return Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(text));
        }
        
        /// <summary>
        /// 解压字符串
        /// </summary>
        private string DecompressString(string compressedText)
        {
            try
            {
                var bytes = Convert.FromBase64String(compressedText);
                return System.Text.Encoding.UTF8.GetString(bytes);
            }
            catch
            {
                // 如果解压失败，假设是未压缩的数据
                return compressedText;
            }
        }
        
        /// <summary>
        /// 标记数据为脏数据
        /// </summary>
        public void MarkDirty()
        {
            isDirty = true;
        }
        
        /// <summary>
        /// 强制保存
        /// </summary>
        public void ForceSave()
        {
            SaveAllData();
        }
        
        /// <summary>
        /// 删除所有保存的数据
        /// </summary>
        public void DeleteAllSavedData()
        {
            try
            {
                if (Directory.Exists(dataDirectory))
                {
                    Directory.Delete(dataDirectory, true);
                    Directory.CreateDirectory(dataDirectory);
                }
                
                if (enableDataLogging)
                {
                    Debug.Log("[DataPersistence] All saved data deleted");
                }
            }
            catch (Exception ex)
            {
                Debug.LogError($"[DataPersistence] Error deleting saved data: {ex.Message}");
            }
        }
        
        /// <summary>
        /// 获取持久化统计信息
        /// </summary>
        public string GetPersistenceStats()
        {
            var stats = $"Total Saves: {totalSaves}, Total Loads: {totalLoads}\n";
            stats += $"Last Save: {lastSaveTimestamp:yyyy-MM-dd HH:mm:ss}\n";
            stats += $"Last Load: {lastLoadTimestamp:yyyy-MM-dd HH:mm:ss}\n";
            stats += $"Auto Save: {(autoSaveEnabled ? "Enabled" : "Disabled")} ({autoSaveInterval}s)\n";
            stats += $"Data Directory: {dataDirectory}";
            
            return stats;
        }
        
        /// <summary>
        /// 设置持久化参数
        /// </summary>
        public void SetPersistenceParameters(bool autoSave, float interval, bool compress, int maxBackups)
        {
            autoSaveEnabled = autoSave;
            autoSaveInterval = interval;
            compressData = compress;
            maxBackupFiles = maxBackups;
            
            MarkDirty();
        }
        
        /// <summary>
        /// 检查数据文件是否存在
        /// </summary>
        public bool HasSavedData()
        {
            return File.Exists(memoryFilePath) || File.Exists(scratchFilePath) || File.Exists(spatialFilePath);
        }
    }
    
    // 数据持久化结构定义
    [System.Serializable]
    public class MemoryPersistenceData
    {
        public string version;
        public DateTime timestamp;
        public List<SerializableMemoryNode> associativeMemories;
        public SerializableSpatialMemory spatialMemory;
    }
    
    [System.Serializable]
    public class ScratchPersistenceData
    {
        public string version;
        public DateTime timestamp;
        public SerializableScratchMemory scratchMemory;
    }
    
    [System.Serializable]
    public class ConfigPersistenceData
    {
        public string version;
        public DateTime timestamp;
        public bool autoSaveEnabled;
        public float autoSaveInterval;
        public bool compressData;
        public bool encryptData;
        public int maxBackupFiles;
        public int totalSaves;
        public int totalLoads;
        public DateTime lastSaveTimestamp;
        public DateTime lastLoadTimestamp;
    }
}